#include "sys_uart.h"
#include "sys_clock.h"
#include "sys_dram.h"
#include "sys_gpio.h"
#include "sys_delay.h"
#include "sys_lcd.h"
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "sys_spi.h"
//-----------------------
#include "sys_lcd_conf.h"
//-----------------------
/*---------------------------------------------------
在sys_lcd_conf.h中配置LCD信息
----------------------------------------------------*/

__align(4) unsigned short *BT; //
void open_LCD_LED(void) {}	   // 开背光
void open_LCD_Power(void) {}   // 打开LCD电源
/*---------------------------------------------------
	显示logo
----------------------------------------------------*/
void _Draw16bmp(int x, int y, int w, int h, short *p)
{
	int Xn, Yn;
	unsigned short *T_BT;
	T_BT = BT;
	for (Yn = 0; Yn < h; Yn++)
	{
		T_BT = BT + (y + Yn) * XSIZE_PHYS + x;
		for (Xn = 0; Xn < w; Xn++)
		{
			*(T_BT + Xn) = *p++; // 连续写入图片数据
		}
	}
}

void read_start_logo(uint32_t addr)
{
	int i = 0;
	char BOOTBMP[8] = "eGON.BMP";
	char file_head[32];
	uint32_t file_size = 0;
	uint32_t BMP_W = 0, BMP_H = 0, BMP_bit = 0;
	uint32_t LCDbuffAddr = 0x81B00000; // RAM 24M显存地址
	uint32_t bmpAddr = 0x81000000;	   // RAM 16M处 Logo bmp 存储地址

	// 读文件头
	sys_spi_flash_read(SPI0, addr, file_head, 32);

	// 判断类型
	sysprintf("Read Logo bmp...\r\n");
	for (i = 0; i < 8; i++)
	{
		if (file_head[4 + i] != BOOTBMP[i])
		{
			break;
		}
	}
	if (i == 8) // LOGO BMP
	{
		// 读文件大小
		file_size = file_head[0x13] << 24 | file_head[0x12] << 16 | file_head[0x11] << 8 | file_head[0x10];
		file_size = file_size - 32 - 8;
		sysprintf("Bmp at Flash 0x%08x\r\n", addr);
		sysprintf("File Size %d\r\n", file_size);

		// 读,色位宽,BMP宽,高
		BMP_bit = file_head[0x19];
		BMP_W = file_head[0x1b] << 8 | file_head[0x1a];
		BMP_H = file_head[0x1d] << 8 | file_head[0x1c];
		sysprintf("BMP-bit=%d\r\n", BMP_bit);
		sysprintf("BMP-W=%d\r\n", BMP_W);
		sysprintf("BMP-H=%d\r\n", BMP_H);

		// 读入BMP文件
		sysprintf("Read bmp to RAM 0x%08x \r\n", bmpAddr);
		sys_spi_flash_read(SPI0, addr + 32 + 8, (uint32_t *)bmpAddr, file_size);

		// 初始化LCD
		open_LCD_Power();
		BT = (unsigned short *)(LCDbuffAddr);
		i = XSIZE_PHYS * YSIZE_PHYS / 2;
		for (; i >= 0; i--)
		{
			*(((uint32_t *)LCDbuffAddr) + i) = 0;
		}
		Sys_LCD_Init(XSIZE_PHYS, YSIZE_PHYS, (uint32_t *)LCDbuffAddr, NULL);
		// 图片内存写入显存
		_Draw16bmp((XSIZE_PHYS - BMP_W) / 2, (YSIZE_PHYS - BMP_H) / 2, BMP_W, BMP_H, (short *)bmpAddr);
		delay_ms(300);
		// 开LCD背光
		open_LCD_LED();
	}
	else
	{
		sysprintf("Logo not found\r\n");
	}
}

void start_app(uint32_t addr)
{
	int i;
	char BOOTEXE[8] = "eGON.EXE";
	void (*fw_func)(void);
	uint32_t executeAddr = 0x80000000;		   // RAM 程序执行地址
	uint32_t spiReadExecPo = 0x50000 - 0x6000; // FLASH 有Logo时读程序的偏移位置 [可显示480x272 16位Logo图片]

	char file_head[32];
	uint32_t file_size = 0;

	addr += spiReadExecPo;
	sys_spi_flash_read(SPI0, addr, file_head, 32); // 读文件头
	sysprintf("\r\nRead program addr: %x\r\n", addr);

	for (i = 0; i < 8; i++)
	{
		if (file_head[4 + i] != BOOTEXE[i])
		{
			break;
		}
	}
	if (i == 8) // 可执行文件
	{
		sysprintf("Read EXEC...\r\n");
		// 读文件大小
		file_size = file_head[0x13] << 24 | file_head[0x12] << 16 | file_head[0x11] << 8 | file_head[0x10];
		file_size = file_size - 32;
		sysprintf("Program at Flash 0x%08x\r\n", addr);
		sysprintf("File Size %d \r\n", file_size);
		// 读文件
		sysprintf("Read exec to RAM 0x%08x \r\n", executeAddr);
		sys_spi_flash_read(SPI0, addr + 32, (uint32_t *)(executeAddr), file_size);
		// 执行
		sysprintf("EXEC 0x80000000...\r\n");

		fw_func = (void (*)(void))(executeAddr);
		fw_func();
	}
}

/*---------------------------------------------------
---- main
---- main
----------------------------------------------------*/
int main(void)
{
	uint32_t spireadAddr = 0x6000;			   // FLASH 24k位置 没有LOGO则为程序地址
	uint32_t CPU_Frequency_hz = 408 * 1000000; // HZ

	int dram_size = sys_dram_init(); // 初始化必须在时钟初始化以前，延时原因
	sys_clock_init(CPU_Frequency_hz);

	Sys_Uart_Init(UART0, CPU_Frequency_hz, 115200, 0);
	Sys_Uart_Init(UART1, CPU_Frequency_hz, 115200, 0);
	Sys_Uart_Init(UART2, CPU_Frequency_hz, 115200, 0);

	Sys_SET_UART_DBG(UART0);
	sysprintf("\r\nUART0\r\n");
	Sys_SET_UART_DBG(UART1);
	sysprintf("\r\nUART1\r\n");
	Sys_SET_UART_DBG(UART2);
	sysprintf("\r\nUART2\r\n");

	Sys_SET_UART_DBG(UART0);

	sysprintf("\r\n");
	sysprintf("F1C%d00S BOOT START...\r\n", dram_size / 32);
	sysprintf("CPU Frequency:%d Hz\r\n", CPU_Frequency_hz);
	sysprintf("DRAM Size: %d MB\r\n", dram_size);
	sysprintf("\r\n");

	spi_flash_init(SPI0);

	read_start_logo(spireadAddr);

	start_app(spireadAddr);

	sysprintf("OUT...\r\n");
	while (1)
	{
	}
}
